package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.clients.baseinfo.BaseCustomer;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.baseinfo.DescByCodeDTO;
import com.chenfan.mcn.constant.BillCodeCst;
import com.chenfan.mcn.constant.DictTypeCst;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.constant.SeparatorCst;
import com.chenfan.mcn.dao.DiscountApprovalMapper;
import com.chenfan.mcn.dao.StarBasicDataMapper;
import com.chenfan.mcn.dao.YearFrameContractMapper;
import com.chenfan.mcn.dao.YearSupplementaryAgreementMapper;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.common.extension.dict.DictStream;
import com.chenfan.common.extension.dict.DictTranslationUtils;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.ApprovalFlowDTO;
import com.chenfan.mcn.model.dto.YearFrameContractSearchDTO;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.service.ApprovalCallbackService;
import com.chenfan.mcn.service.ApprovalFlowService;
import com.chenfan.mcn.service.YearFrameContractService;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.mcn.extension.excel.ExcelUtils;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 年框合同 服务实现类
 * </p>
 *
 * @author lizhejin
 * @since 2021-01-19
 */
@Service
public class YearFrameContractServiceImpl extends ServiceImpl<YearFrameContractMapper, YearFrameContract> implements YearFrameContractService, ApprovalCallbackService {

    @Autowired
    private YearFrameContractMapper yearFrameContractMapper;

    @Autowired
    private YearSupplementaryAgreementMapper yearSupplementaryAgreementMapper;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private DiscountApprovalMapper discountApprovalMapper;

    @Autowired
    private DiscountApprovalServiceImpl discountApprovalServiceImpl;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private StarBasicDataMapper starBasicDataMapper;


    /**
     * 新增年框合同
     *
     * @param yearFrameContractVO 请求参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveData(YearFrameContractVO yearFrameContractVO) {
        YearFrameContract yearFrameContract = new YearFrameContract();
        BeanUtils.copyProperties(yearFrameContractVO, yearFrameContract);
        if (Objects.isNull(yearFrameContractVO.getId())) {
            //verifyCooperationTime(yearFrameContractVO);
            if (yearFrameContractVO.getContractType().equals(YearContractTypeEnum.ADYearFrame.code()) && StringUtils.isNotBlank(yearFrameContractVO.getDiscountCode())) {
                YearFrameContract isExist = this.isExist(yearFrameContractVO.getTargetType(), yearFrameContractVO.getCustomerId(), yearFrameContractVO.getDiscountCode());
                if (Objects.nonNull(isExist)) {
                    throw new BusinessException(McnErrorCode.EXIST_NON_VOID_CONTRACT);
                }
            }
            yearFrameContract.setYearFrameCode(CodeGenerateHelper.getCode(BillCodeCst.YEAR_FRAME_CONTRACT));
            yearFrameContractMapper.insert(yearFrameContract);
            if (Objects.nonNull(yearFrameContract.getYearStatus()) && yearFrameContract.getYearStatus() == YearStatusEnum.APPROVAL.code()) {
                approvalFlowService.startProcess(yearFrameContract.getId(), yearFrameContract.getYearFrameCode(), ApprovalEnum.YEAR_CONTRACT, JSON.toJSONString(yearFrameContract));
            }
        } else {
            saveVertifyStatus(yearFrameContractVO.getId());
            //verifyCooperationTime(yearFrameContractVO);
            verifyDiscount(yearFrameContract);
            YearFrameContract beforeYearFrameContract = yearFrameContractMapper.selectById(yearFrameContract.getId());
            yearFrameContractMapper.updateById(yearFrameContract);
            if (Objects.nonNull(yearFrameContract.getYearStatus()) && yearFrameContract.getYearStatus() == YearStatusEnum.APPROVAL.code()) {
                approvalFlowService.startProcess(beforeYearFrameContract.getId(), beforeYearFrameContract.getYearFrameCode(), ApprovalEnum.YEAR_CONTRACT, JSON.toJSONString(yearFrameContract));
            }
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(beforeYearFrameContract.getId())
                    .businessType(LogBusinessTypeEnum.YEAR_FRAME_CONTRACT)
                    .compare(beforeYearFrameContract,  yearFrameContract)
                    .build());
        }
        return yearFrameContract.getId();
    }

    private void saveVertifyStatus(YearSupplementaryAgreement yearSupplementaryAgreement) {
        if (yearSupplementaryAgreement.getStatus() != YearStatusEnum.UN_COMMIT.code() &&
                yearSupplementaryAgreement.getStatus() != YearStatusEnum.REJECTED.code() &&
                yearSupplementaryAgreement.getStatus() != YearStatusEnum.CANCEL.code()) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_UPDATE_ERROR);
        }
    }

    private void saveVertifyStatus(Long id) {
        YearFrameContract yearFrameContract = yearFrameContractMapper.selectById(id);
        if (yearFrameContract.getYearStatus() != YearStatusEnum.UN_COMMIT.code() &&
                yearFrameContract.getYearStatus() != YearStatusEnum.REJECTED.code() &&
                yearFrameContract.getYearStatus() != YearStatusEnum.CANCEL.code()) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_UPDATE_ERROR);
        }
    }


    /**
     * 校验折扣返点审批单是否已经关联非作废状态的年框合同
     *
     * @param yearFrameContract {@link YearFrameContract}
     */
    public void verifyDiscount(YearFrameContract yearFrameContract) {
        if (yearFrameContract.getContractType().equals(YearContractTypeEnum.ADYearFrame.code()) && StringUtils.isNotBlank(yearFrameContract.getDiscountCode())) {
            YearFrameContract isExist = this.isExist(yearFrameContract.getTargetType(), yearFrameContract.getCustomerId(), yearFrameContract.getDiscountCode());
            if (Objects.nonNull(isExist)) {
                if (Objects.nonNull(yearFrameContract.getId()) && !isExist.getId().equals(yearFrameContract.getId())) {
                    throw new BusinessException(McnErrorCode.EXIST_NON_VOID_CONTRACT);
                }
                if (Objects.isNull(yearFrameContract.getId())) {
                    throw new BusinessException(McnErrorCode.EXIST_NON_VOID_CONTRACT);
                }
            }
        }
    }

    /**
     * 新增年框合同补充协议
     *
     * @param yearSupplementaryAgreementVO 请求参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSupplementaryAgreement(YearSupplementaryAgreementVO yearSupplementaryAgreementVO) throws BusinessException {
        YearSupplementaryAgreement yearSupplementaryAgreement = new YearSupplementaryAgreementVO();
        BeanUtils.copyProperties(yearSupplementaryAgreementVO, yearSupplementaryAgreement);
        if (Objects.isNull(yearSupplementaryAgreementVO.getId())) {
            yearSupplementaryAgreement.setAgreementCode(CodeGenerateHelper.getCode(BillCodeCst.YEAR_FRAME_AGREEMENT));
            yearSupplementaryAgreementMapper.insert(yearSupplementaryAgreement);
            if (Objects.nonNull(yearSupplementaryAgreement.getStatus()) && yearSupplementaryAgreement.getStatus() == YearStatusEnum.APPROVAL.code()) {
                approvalFlowService.startProcess(yearSupplementaryAgreement.getId(), yearSupplementaryAgreement.getYearId(), yearSupplementaryAgreement.getAgreementCode(), ApprovalEnum.YEAR_SUPPLEMENTARY_AGREEMENT, JSON.toJSONString(yearSupplementaryAgreement), null);
            }
        } else {
            yearSupplementaryAgreement.setId(yearSupplementaryAgreementVO.getId());
            YearSupplementaryAgreement beforeData = yearSupplementaryAgreementMapper.selectById(yearSupplementaryAgreement.getId());
            saveVertifyStatus(beforeData);
            yearSupplementaryAgreementMapper.updateById(yearSupplementaryAgreement);
            if (Objects.nonNull(yearSupplementaryAgreement.getStatus()) && yearSupplementaryAgreement.getStatus() == YearStatusEnum.APPROVAL.code()) {
                approvalFlowService.startProcess(beforeData.getId(), beforeData.getYearId(), beforeData.getAgreementCode(), ApprovalEnum.YEAR_SUPPLEMENTARY_AGREEMENT, JSON.toJSONString(yearSupplementaryAgreement), null);
            }
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(beforeData.getId())
                    .businessType(LogBusinessTypeEnum.YEAR_SUPPLEMENTARY_AGREEMENT)
                    .compare(beforeData,  yearSupplementaryAgreementMapper.selectById(yearSupplementaryAgreementVO.getId()))
                    .build());
        }
    }

    /**
     * 修改年框合同审批状态
     *
     * @param yearFrameContract {@link YearFrameContract}
     * @return {@link Boolean}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changeStatus(YearFrameContract yearFrameContract) {
        YearFrameContract entity = yearFrameContractMapper.selectById(yearFrameContract.getId());
        BusinessAssert.notNull(entity, McnErrorCode.YEAR_NOT_EXISTS);
        YearFrameContract updateEntity = new YearFrameContract();
        updateEntity.setId(entity.getId());
        validateStatus(entity, yearFrameContract.getYearStatus());
        updateEntity.setYearStatus(yearFrameContract.getYearStatus());
        boolean result = this.updateById(updateEntity);
        if (result) {
            YearFrameContract newYear = yearFrameContractMapper.selectById(yearFrameContract.getId());
            if (newYear.getYearStatus() == YearStatusEnum.APPROVAL.code()) {
                approvalFlowService.startProcess(newYear.getId(), newYear.getYearFrameCode(), ApprovalEnum.YEAR_CONTRACT, JSON.toJSONString(newYear));
            }
            if (newYear.getYearStatus() == YearStatusEnum.CANCEL.code() || newYear.getYearStatus() == YearStatusEnum.INVALID.code()) {
                approvalFlowService.revokeProcess(newYear.getId(), ApprovalEnum.YEAR_CONTRACT.getProcessId());
            }
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                    .businessType(LogBusinessTypeEnum.YEAR_FRAME_CONTRACT)
                    .compare(entity,  newYear)
                    .build());
        }
        return result;
    }


    /**
     * 判断审批状态
     *
     * @param yearFrameContract {@link YearFrameContract}
     * @param status            {@link Integer}
     */
    @SuppressWarnings("AlibabaAvoidComplexCondition")
    private void validateStatus(YearFrameContract yearFrameContract, Integer status) {
        if (yearFrameContract.getYearStatus().equals(YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.YEAR_INVALID);
        }
        if (status.equals(YearStatusEnum.PASSED.code()) || status.equals(YearStatusEnum.REJECTED.code())) {
            if (yearFrameContract.getYearStatus().equals(YearStatusEnum.CANCEL.code())) {
                throw new BusinessException(McnErrorCode.YEAR_CANCELED);
            }
        }
        if (yearFrameContract.getYearStatus() == YearStatusEnum.UN_COMMIT.code() &&
                (status != YearStatusEnum.APPROVAL.code() && status != YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_COMMIT_ERROR);
        }
        if (yearFrameContract.getYearStatus() == YearStatusEnum.APPROVAL.code() &&
                (status != YearStatusEnum.CANCEL.code() && status != YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_CANCEL_ERROR);
        }
        if (yearFrameContract.getYearStatus() == YearStatusEnum.PASSED.code() &&
                (status != YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_PASSED_ERROR);
        }
        if (yearFrameContract.getYearStatus() == YearStatusEnum.REJECTED.code() &&
                (status != YearStatusEnum.APPROVAL.code() && status != YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_REJECTED_ERROR);
        }
        if (yearFrameContract.getYearStatus() == YearStatusEnum.CANCEL.code() &&
                (status != YearStatusEnum.APPROVAL.code() && status != YearStatusEnum.INVALID.code())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_CANCEL_ERROR);
        }
    }

    /**
     * 根据客户获取折扣审批单
     *
     * @param customerId {@link String}
     * @return {@link DiscountApproval}
     */
    @Override
    public List<DiscountApprovalVO> getDiscountApproval(Long customerId, boolean selected) throws BusinessException {
        List<DiscountApprovalVO> dataList = discountApprovalMapper.selectByCustomerId(customerId, selected);
        if (CollectionUtils.isNotEmpty(dataList)) {
            List<Long> customerIdList = new ArrayList<>(Collections.singletonList(customerId));
            Map<Long, BaseCustomer> customerMapping = baseInfoClient.getMcnCustomerByIds(customerIdList).getObj();
            if (Objects.nonNull(customerMapping) && customerMapping.size() > 0) {
                dataList.forEach(vo -> {
                    vo.setCustomerName(customerMapping.get(customerId).getCustomerNameC());
                });
            }
        }
        return dataList;
    }

    /**
     * 详情
     *
     * @param yearId {@link Long}
     * @return 返回值
     */
    @Override
    public YearFrameContractVO info(Long yearId) {
        YearFrameContractVO yearFrameContractVO = new YearFrameContractVO();
        YearFrameContractVO yearFrameContract = yearFrameContractMapper.selectByYearId(yearId, ApprovalEnum.YEAR_CONTRACT.getProcessId());
        if (Objects.isNull(yearFrameContract)) {
            throw new BusinessException(McnErrorCode.PARAM_ERROR);
        }
        BeanUtils.copyProperties(yearFrameContract, yearFrameContractVO);
        if (Objects.nonNull(yearFrameContract.getDiscountId())) {
            DiscountInfoVO approvalInfo = discountApprovalServiceImpl.getDiscountApprovalInfo(yearFrameContract.getDiscountId());
            yearFrameContractVO.setDiscountInfoVO(approvalInfo);
        }
        List<YearSupplementaryAgreementVO> yearSupplementaryAgreementVos = yearSupplementaryAgreementMapper.selectByYearId(yearId, ApprovalEnum.YEAR_SUPPLEMENTARY_AGREEMENT.getProcessId());
        yearSupplementaryAgreementVos.forEach(x -> x.setYearCode(yearFrameContractVO.getYearFrameCode()));
        yearFrameContractVO.setYearSupplementaryAgreementList(yearSupplementaryAgreementVos);
        if(NumberCst.ONE.equals(yearFrameContract.getTargetType())) {
            List<Long> customerIdList = new ArrayList<>(Collections.singletonList(yearFrameContractVO.getCustomerId()));
            Map<Long, BaseCustomer> customerMapping = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () -> baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
            BaseCustomer baseCustomer = customerMapping.get(yearFrameContractVO.getCustomerId());
            yearFrameContractVO.setCustomerName(Objects.nonNull(baseCustomer) ? baseCustomer.getCustomerNameC(): "");
        } else if(NumberCst.TWO.equals(yearFrameContract.getTargetType())) {
            StarBasicData starBasicData = starBasicDataMapper.selectById(yearFrameContractVO.getCustomerId());
            yearFrameContractVO.setCustomerName(Objects.nonNull(starBasicData) ? starBasicData.getStarNickname() : "");
        }

        List<Long> flowList = new ArrayList<>(Collections.singletonList(yearFrameContract.getFlowId()));
        flowList.addAll(yearSupplementaryAgreementVos.stream().map(YearSupplementaryAgreementVO::getFlowId).distinct().collect(Collectors.toList()));
        JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
        if (Objects.nonNull(flowMapping)) {
            if (flowMapping.size() > 0 && Objects.nonNull(yearFrameContract.getFlowId())) {
                yearFrameContractVO.setFlowStatusName(flowMapping.getString(yearFrameContract.getFlowId().toString()));
                yearSupplementaryAgreementVos.forEach(y -> {
                    if (Objects.nonNull(y.getFlowId())) {
                        y.setFlowStatusName(flowMapping.getString(y.getFlowId().toString()));
                    }
                });
            }
        }
        //字典翻译
        DictTranslationUtils.translation(() -> DictStream.of(
                DictStream.map(DictTypeCst.SUBJECT_OF_CONTRACT, YearFrameContractVO::getContractSubject, YearFrameContractVO::setContractSubjectName),
                DictStream.map(DictTypeCst.YEAR_FRAME_CONTRACT, YearFrameContractVO::getContractType, YearFrameContractVO::setContractTypeName)
                ), (dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                yearFrameContractVO
        );
        return yearFrameContractVO;
    }


    /**
     * 年框合同分页数据
     *
     * @param page                       {@link }
     * @param searchDTO {@link YearFrameContractSearchDTO}
     * @return
     */
    @Override
    public Page<YearFrameVO> getList(McnPage<YearFrameVO> page, YearFrameContractSearchDTO searchDTO) {
        searchDTO.setProcessId(ApprovalEnum.YEAR_CONTRACT.getProcessId());
        searchDTO.setAlias("yfc.");
        if (Objects.nonNull(searchDTO.getApprovalStatus())) {
            List<Long> srcList = approvalFlowService.getSrcList(Lists.newArrayList(searchDTO.getApprovalStatus()), searchDTO.getProcessId());
            if (CollectionUtil.isEmpty(srcList)) {
                return new Page<>();
            }
            searchDTO.setSrcIds(srcList);
        }
        Page<YearFrameVO> list = yearFrameContractMapper.getList(page, searchDTO);
        if(CollectionUtils.isNotEmpty(list.getRecords())) {
            List<Long> customerIdList = list.getRecords().stream().filter(e -> NumberCst.ONE.equals(e.getTargetType())).map(YearFrameVO::getCustomerId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () -> baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
            List<Long> starIdList = list.getRecords().stream().filter(e -> NumberCst.TWO.equals(e.getTargetType())).map(YearFrameVO::getCustomerId).distinct().collect(Collectors.toList());
            List<StarBasicData> starList = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(starIdList), () -> starBasicDataMapper.selectBatchIds(starIdList), null);
            Map<Long, String> starMap = CommonUtil.defaultList(starList).stream().collect(Collectors.toMap(k -> k.getId(), v -> v.getStarNickname()));
            List<Long> flowList = list.getRecords().stream().map(YearFrameVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
            list.getRecords().forEach(vo -> {
                if(NumberCst.ONE.equals(vo.getTargetType())) {
                    vo.setCustomerName(CommonUtil.defaultString(customerMapping, vo.getCustomerId(), BaseCustomer::getCustomerNameC));
                } else if(NumberCst.TWO.equals(vo.getTargetType())) {
                    vo.setCustomerName(starMap.get(vo.getCustomerId()));
                }
                vo.setFlowStatusName(CommonUtil.defaultString(flowMapping, vo.getFlowId()));
            });
            //字典翻译
            DictTranslationUtils.translation(() -> DictStream.of(
                    DictStream.map(DictTypeCst.SUBJECT_OF_CONTRACT, YearFrameVO::getContractSubject, YearFrameVO::setContractSubjectName),
                    DictStream.map(DictTypeCst.YEAR_FRAME_CONTRACT, YearFrameVO::getContractType, YearFrameVO::setContractTypeName)
                    ), (dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                    list.getRecords()
            );
        }
        return list;
    }

    /**
     * 导出excel
     *
     * @param searchDTO {@link YearFrameContractSearchDTO}
     * @param response                   {@link HttpServletResponse}
     */
    @Override
    public void exportExcel(YearFrameContractSearchDTO searchDTO, HttpServletResponse response) throws Exception {
        searchDTO.setProcessId(ApprovalEnum.YEAR_CONTRACT.getProcessId());
        searchDTO.setYsaProcessId(ApprovalEnum.YEAR_SUPPLEMENTARY_AGREEMENT.getProcessId());
        searchDTO.setAlias("yfc.");
        if (Objects.nonNull(searchDTO.getApprovalStatus())) {
            List<Long> srcList = approvalFlowService.getSrcList(Lists.newArrayList(searchDTO.getApprovalStatus()), searchDTO.getProcessId());
            if (CollectionUtil.isEmpty(srcList)) {
                ExcelUtils.exportExcel(new ArrayList<>(), "年框合同", YearFrameVO.class, "年框合同导出.xlsx", response);
                return;
            }
            searchDTO.setSrcIds(srcList);
        }
        List<YearFrameVO> list = CommonUtil.defaultList(yearFrameContractMapper.exportList(searchDTO));
        if(CollectionUtils.isNotEmpty(list)) {
            List<Long> customerIdList = list.stream().filter(e -> NumberCst.ONE.equals(e.getTargetType())).map(YearFrameVO::getCustomerId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () -> baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
            List<Long> starIdList = list.stream().filter(e -> NumberCst.TWO.equals(e.getTargetType())).map(YearFrameVO::getCustomerId).distinct().collect(Collectors.toList());
            List<StarBasicData> starList = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(starIdList), () -> starBasicDataMapper.selectBatchIds(starIdList), null);
            Map<Long, String> starMap = CommonUtil.defaultList(starList).stream().collect(Collectors.toMap(k -> k.getId(), v -> v.getStarNickname()));
            list.forEach(x -> {
                if(NumberCst.ONE.equals(x.getTargetType())) {
                    if(customerMapping.containsKey(x.getCustomerId())) {
                        x.setCustomerName(customerMapping.get(x.getCustomerId()).getCustomerNameC());
                    }
                } else if(NumberCst.TWO.equals(x.getTargetType())) {
                    x.setCustomerName(starMap.get(x.getCustomerId()));
                }
            });

            List<Long> longList = new ArrayList<>();
            for (YearFrameVO s : list) {
                List<ExportYearSupplementaryVO> exportYearSupplementaryVO = s.getExportYearSupplementaryVO();
                if (Objects.nonNull(exportYearSupplementaryVO)) {
                    List<Long> flowIds = exportYearSupplementaryVO.stream().map(ExportYearSupplementaryVO::getFlowId).distinct().collect(Collectors.toList());
                    longList.addAll(flowIds);
                    for (ExportYearSupplementaryVO supplementaryVO : exportYearSupplementaryVO) {
                        String mainChanges = supplementaryVO.getMainChanges();
                        JSONArray jsonObject = JSONArray.parseArray(mainChanges);
                        supplementaryVO.setMainChangesName(getMainChanges(jsonObject));
                    }
                }
            }
            List<Long> collectList = longList.stream().distinct().collect(Collectors.toList());
            List<Long> flowList = list.stream().map(YearFrameVO::getFlowId).distinct().collect(Collectors.toList());
            flowList.addAll(collectList);
            JSONObject flowMapping = null;
            if (flowList.size() > 0) {
                flowMapping = approvalFlowService.getFlowStatus(flowList);
            }
            if (Objects.nonNull(flowMapping)) {
                JSONObject finalFlowMapping = flowMapping;
                list.forEach(vo -> {
                    if (finalFlowMapping.size() > 0 && Objects.nonNull(vo.getFlowId())) {
                        vo.setFlowStatusName(finalFlowMapping.getString(vo.getFlowId().toString()));
                    }
                });
                for (YearFrameVO yearFrameVO : list) {
                    List<ExportYearSupplementaryVO> exportYearSupplementaryVO = yearFrameVO.getExportYearSupplementaryVO();
                    exportYearSupplementaryVO.forEach(y -> {
                        if (Objects.nonNull(y.getFlowId())) {
                            y.setFlowStatusName(finalFlowMapping.getString(y.getFlowId().toString()));
                        }
                    });
                }
            }
        }
        //字典翻译
        DictTranslationUtils.translation(() -> DictStream.of(
                DictStream.map(DictTypeCst.SUBJECT_OF_CONTRACT, YearFrameVO::getContractSubject, YearFrameVO::setContractSubjectName),
                DictStream.map(DictTypeCst.YEAR_FRAME_CONTRACT, YearFrameVO::getContractType, YearFrameVO::setContractTypeName)
                ), (dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                list
        );
        ExcelUtils.exportExcel(list, "年框合同", YearFrameVO.class, "年框合同导出.xlsx", response);
    }


    /**
     * 拼接主要变更内容
     *
     * @param jsonArray {@link JSONArray}
     * @return {@link String}
     */
    public String getMainChanges(JSONArray jsonArray) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < jsonArray.size(); i++) {
            String statusName = YearAgreementChangeContentEnum.getStatusName(Integer.parseInt(jsonArray.get(i).toString()));
            if (i == 0) {
                stringBuilder.append(statusName);
            } else {
                stringBuilder.append(SeparatorCst.COMMA).append(statusName);
            }
        }
        return stringBuilder.toString();
    }

    /**
     * 获取所有的年框合同
     *
     * @param yearFrameContractSearchDTO {@link YearFrameContractSearchDTO}
     * @return {@link List<YearFrameContractVO>}
     */
    @Override
    public List<YearFrameContractVO> getYearCode(YearFrameContractSearchDTO yearFrameContractSearchDTO) {
        yearFrameContractSearchDTO.setAlias("yfc.");
        return yearFrameContractMapper.getYearCode(yearFrameContractSearchDTO);
    }

    /**
     * 自动带出变更前后折扣返点审批单数据
     *
     * @param yearCode {@link String}
     * @return {@link }
     */
    @Override
    public ChangeDiscountApproval getChangeDiscountApproval(String yearCode) {
        YearFrameContract yearFrameContract = yearFrameContractMapper.selectByYearCode(yearCode);
        BusinessAssert.notNull(yearFrameContract, McnErrorCode.YEAR_NOT_EXISTS);
        ChangeDiscountApproval changeDiscountApproval = new ChangeDiscountApproval();
        changeDiscountApproval.setDiscountApprovalBeforeChange(yearFrameContract.getDiscountCode());
        changeDiscountApproval.setContactSubjectBeforeChange(yearFrameContract.getContractSubject());
        Long customerId = yearFrameContract.getCustomerId();
        if (yearFrameContract.getContractType().equals(YearContractTypeEnum.ADYearFrame.code())) {
            List<DiscountApprovalVO> voList = this.getDiscountApproval(customerId, false);
            if (CollectionUtils.isNotEmpty(voList)) {
                changeDiscountApproval.setDiscountApprovalAfterChange(voList.get(0).getDiscountCode());
            }
        }
        changeDiscountApproval.setContactSubjectAfterChange(yearFrameContract.getContractSubject());
        changeDiscountApproval.setYearId(yearFrameContract.getId());
        changeDiscountApproval.setBeforeContractingId(yearFrameContract.getContractingId());
        changeDiscountApproval.setContractingId(yearFrameContract.getContractingId());
        return changeDiscountApproval;
    }


    /**
     * 校验同一客户，同一折扣审批单，非作废状态下是否已经存在年框合同
     * @param targetType   {@link Integer}
     * @param customerId   {@link Long}
     * @param discountCode {@link String}
     * @return {@link YearFrameContract}
     */
    @Override
    public YearFrameContract isExist(Integer targetType, Long customerId, String discountCode) {
        return yearFrameContractMapper.isExist(targetType, customerId, discountCode);
    }

    @Override
    public Page<CusYearContractVO> getCusYearContract(McnPage<CusYearContractVO> mcnPage, Long customerId) {
        // 查询客户关联年框合同
        Page<CusYearContractVO> cusYearContractPage = yearFrameContractMapper.getCusYearContract(mcnPage, customerId, ApprovalEnum.YEAR_CONTRACT.getProcessId());

        List<CusYearContractVO> yearContractList = cusYearContractPage.getRecords();
        if (CollectionUtil.isNotEmpty(yearContractList)) {
            List<Long> flowList = yearContractList.stream().map(CusYearContractVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            // 审批名称

            JSONObject flowMapping = null;
            if (flowList.size() > 0) {
                flowMapping = approvalFlowService.getFlowStatus(flowList);
            }
            JSONObject finalFlowMapping = flowMapping;
            yearContractList.forEach(contract -> {
                if (Objects.nonNull(finalFlowMapping) && finalFlowMapping.size() > 0 && Objects.nonNull(contract.getFlowId())) {
                    contract.setFlowStatusName(finalFlowMapping.getString(contract.getFlowId().toString()));
                }
                contract.setApprovalStatusName(YearStatusEnum.getStatusName(contract.getYearStatus()));
            });
        }
        return cusYearContractPage;
    }

    /**
     * 客户下所有年框合同
     *
     * @param customerId 客户id
     * @return 年框合同列表
     */
    @Override
    public List<YearFrameContractVO> getYearContractByCustomerId(Long customerId) {
        Date now = new Date();
        List<YearFrameContractVO> yearFrameContracts = CommonUtil.defaultList(yearFrameContractMapper.selectList(Wrappers.lambdaQuery(YearFrameContract.class)
                .eq(YearFrameContract::getYearStatus, YearStatusEnum.PASSED.code())
                .le(YearFrameContract::getCooperationStartDate, now)
                .ge(YearFrameContract::getCooperationEndDate, now)
                .eq(YearFrameContract::getCustomerId, customerId))
        ).stream().map(e -> {
            YearFrameContractVO yearFrameContractVO = new YearFrameContractVO();
            BeanUtils.copyProperties(e, yearFrameContractVO);
            return yearFrameContractVO;
        }).collect(Collectors.toList());
        //字典翻译
        DictTranslationUtils.translation(() -> DictStream.of(
                DictStream.map(DictTypeCst.YEAR_FRAME_CONTRACT, YearFrameContractVO::getContractType, YearFrameContractVO::setContractTypeName)
                ), (dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                yearFrameContracts
        );
        return yearFrameContracts;
    }

    @Override
    public List<StarRebateContractYearFrameVO> getYearFrameContractForStarRebate(Long starId) {
        List<YearFrameContract> dataList = yearFrameContractMapper.getYearFrameContract(NumberCst.TWO, starId);
        if (CollectionUtils.isEmpty(dataList)) {
            return new ArrayList<>(0);
        }
        StarBasicData starBasicData = starBasicDataMapper.selectById(starId);
        List<StarRebateContractYearFrameVO> voList = dataList.stream().map(data -> {
            StarRebateContractYearFrameVO vo = new StarRebateContractYearFrameVO();
            BeanUtils.copyProperties(data, vo);
            if(Objects.nonNull(starBasicData)) {
                vo.setCustomerName(starBasicData.getStarNickname());
            }
            return vo;
        }).collect(Collectors.toList());
        //字典翻译
        DictTranslationUtils.translation(() -> DictStream.of(
                DictStream.map(DictTypeCst.YEAR_FRAME_CONTRACT, StarRebateContractYearFrameVO::getContractType, StarRebateContractYearFrameVO::setContractTypeName)
                ), (dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                voList
        );
        return voList;
    }

    /**
     * 审批回调
     *
     * @param approvalFlowDTO 流程对对象
     * @param status          最后节点的同意 false 拒绝
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvalCallback(ApprovalFlowDTO approvalFlowDTO, Boolean status) {
        YearFrameContract yearFrameContract = this.baseMapper.selectById(approvalFlowDTO.getSrcId());
        approvalFlowDTO.setSrcCode(yearFrameContract.getYearFrameCode());
        approvalFlowDTO.addSubmitInfoIfNull(yearFrameContract);
        if (Objects.isNull(status)) {
            //审批流配置-接入待办
            return;
        }
        yearFrameContract.setYearStatus(status ? YearStatusEnum.PASSED.code() : YearStatusEnum.REJECTED.code());
        yearFrameContract.setUpdateBy(approvalFlowDTO.getUserId());
        yearFrameContract.setUpdateName(approvalFlowDTO.getUserName());
        yearFrameContract.setUpdateDate(new Date());
        this.baseMapper.updateById(yearFrameContract);
        approvalFlowService.sendNotify(approvalFlowDTO, yearFrameContract.getId(), yearFrameContract.getYearFrameCode()
                , ApprovalEnum.YEAR_CONTRACT, status, yearFrameContract.getCreateBy(), yearFrameContract.getCreateName());
    }
}
